package com.example.voucher.contract;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.function.BinaryOperator;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.example.voucher.config.bo.FieldReducingConfigBO;
import com.example.voucher.enums.ReducingRuleEnum;
import com.google.common.collect.Lists;

/**
 * 适配目标数据
 * 
 * @author jie.deng
 * @date 2020/11/04
 */
public interface VoucherItemAccessor extends VoucherItemCapable {
    
    public static final Logger LOGGER = LoggerFactory.getLogger(VoucherItemAccessor.class);

    void setOrgTitleCode(String orgTitleCode);

    void setOrgTitleName(String orgTitleName);
    
    void setOrgTitleFullname(String orgTitleFullname);

    void setOppoOrgTitleCode(String oppoOrgTitleCode);

    void setOppoOrgTitleName(String oppoOrgTitleName);
    
    void setOppoOrgTitleFullname(String oppoOrgTitleFullname);

    void setInvoiceCode(String invoiceCode);

    void setInvoiceNo(String invoiceNo);

    void setInvoiceDate(Date invoiceDate);

    void setInvoiceId(Long invoiceId);

    void setInvoiceSn(Integer invoiceSnId);

    void setInvoiceSnId(Long invoiceSnId);

    void setWeight(BigDecimal weight);

    void setTotalWeight(BigDecimal weight);

    void setPreTaxAmount(BigDecimal preTaxAmount);

    void setTotalPreTaxAmount(BigDecimal weight);

    void setTaxAmount(BigDecimal taxAmount);

    void setTotalTaxAmount(BigDecimal weight);

    void setPriceTaxAmount(BigDecimal priceTaxAmount);

    void setTotalPriceTaxAmount(BigDecimal weight);

    void setOrderCode(String orderCode);

    void setOrderDate(Date orderDate);

    void setRcCode(String rcCode);

    void setRcName(String rcName);

    void setProductLine(String productLine);
    
    void setSiteCode(String siteCode);

    void setSiteName(String siteName);

    void setSiteFullname(String siteFullname);

    default BigDecimal getTotalWeight() {
        return BigDecimal.ZERO;
    }

    default BigDecimal getTotalPreTaxAmount() {
        return BigDecimal.ZERO;
    }

    default BigDecimal getTotalTaxAmount() {
        return BigDecimal.ZERO;
    }

    default BigDecimal getTotalPriceTaxAmount() {
        return BigDecimal.ZERO;
    }
    
    default String getFirstItName() {
        return "";
    }

    default Date getFirstInvoiceDate() {
        return null;
    }

    default String getEntryQtyUnit() {
        return "";
    }

    default String getEntryOrderCode() {
        return "";
    }

    default String getEntryInvoiceNo() {
        return "";
    }
    
    default String getAsstOrderCode() {
        return "";
    }

    default String getAsstInvoiceNo() {
        return "";
    }
    
    void setItName(String itName);
    
    void setIcName(String icName);

    void setNow(Date now);

    void setScanDate(Date scanDate);

    void setVerifyDate(Date verifyDate);

    void setAccountDate(Date accountDate);

    void setUnit(String unit);

    void setQtyUnit(String qtyUnit);

    void setFirstItName(String firstItName);

    void setFirstInvoiceDate(Date firstInvoiceDate);

    void setEntryQtyUnit(String entryQtyUnit);

    void setEntryOrderCode(String entryOrderCode);
    
    void setEntryInvoiceNo(String entryInvoiceNo);

    void setAsstInvoiceNo(String asstInvoiceNo);

    void setAsstOrderCode(String asstOrderCode);
    
    static List<String> defaultAvailableReducingField() {
        return Lists.newArrayList("weight", "preTaxAmount", "taxAmount", "priceTaxAmount");
    }

    static List<Pair<String, String>> defaultAvailableReducingPair() {
        List<Pair<String, String>> list = Lists.newArrayList();
        list.add(Pair.of("weight", "totalWeight"));
        list.add(Pair.of("preTaxAmount", "totalPreTaxAmount"));
        list.add(Pair.of("taxAmount", "totalTaxAmount"));
        list.add(Pair.of("priceTaxAmount", "totalPriceTaxAmount"));
        return list;
    }

    public static BinaryOperator<VoucherItemAccessor>
        combinerBinaryOperator(final List<FieldReducingConfigBO> reducingConfigList) {
        return (VoucherItemAccessor t1, VoucherItemAccessor t2) -> {
            VoucherItemAccessor target = null;
            try {
                target = (VoucherItemAccessor)BeanUtils.cloneBean(t1);
                for (FieldReducingConfigBO config : reducingConfigList) {
                    String srcField = config.getSrcField();
                    String reducingRule = config.getReducingRule();
                    String delimiter = config.getDelimiter();
                    Object left = PropertyUtils.getProperty(t1, srcField);
                    Object right = PropertyUtils.getProperty(t2, srcField);
                    BinaryOperator combiner = ReducingRuleEnum.combinerBinaryOperator(reducingRule, left.getClass(), delimiter);
                    left = combiner.apply(left, right);
                    PropertyUtils.setProperty(target, srcField, left);
                }
            } catch (Exception e) {
                LOGGER.error("combinerBinaryOperator", e);
            }
            return target;
        };
    }

}